﻿namespace EFS.RC.CC.Tools.Schedulers
{
	/// <summary>
	/// AgentDialTimeOutn
	/// </summary>
	internal class AgentDialTimeOut : EFS.Common.Async.AsyncRoot
	{
		#region Composition

		// session
		private EFS.RC.CC.Sessions.OfficeService.Operators.HuntQueue.DialIn operatorDialInSession = null;

		// repeat
		private System.Threading.ManualResetEvent resumeOperatorDialInSessionEvent = null;

		#endregion

		#region Constructor
			
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="operatorDialInSession"></param>
		public AgentDialTimeOut(EFS.RC.CC.Sessions.OfficeService.Operators.HuntQueue.DialIn operatorDialInSession)
		{
			// set
			EFS.Common.Verify.Reference(operatorDialInSession, "operatorDialInSession");

			// set
			this.operatorDialInSession = operatorDialInSession;

			// register terminated delegate
			this.operatorDialInSession.AsinkTerminatedDelegate.Register(OnOperatorDialInSessionTerminated);

			// create new wait event
			resumeOperatorDialInSessionEvent = new System.Threading.ManualResetEvent(false);

			// log
			EFS.EventLog.Log.LogInfo("AgentDialTimeOut", this);
		}

		#endregion

		#region Usage

		/// <summary>
		/// Describe this object into a nice formated string
		/// </summary>
		/// <returns></returns>
		public override System.String Describe()
		{
			return System.String.Format("EFS.RC.CC.Tools.Schedulers.AgentDialTimeOut [{0}]", operatorDialInSession.Describe());
		}

		/// <summary>
		/// Begin startup
		/// </summary>
		public EFS.Common.Async.AsyncProcess Start()
		{
			// log
			EFS.EventLog.Log.LogInfo("BeginStartup", this);

			// begin
			return BeginAsyncProcess2(StartAgentDialTimeOut, OnExecuteAgentDialTimeOutComplete);
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Unhandled exception
		/// </summary>
		/// <param name="ex"></param>
		protected override void OnException(System.Exception ex)
		{
			// check
			EFS.Common.Verify.Reference(ex, "ex");

			// log
			EFS.EventLog.Log.LogException(ex, this);
		}

		#endregion

		#region Execute

		/// <summary>
		/// ExecuteAgentDialTimeOut
		/// </summary>
		private void StartAgentDialTimeOut()
		{
			// log
			EFS.EventLog.Log.LogInfo("ExecuteAgentDialTimeOut", this);

			// check wait event
			if (!resumeOperatorDialInSessionEvent.WaitOne(new System.TimeSpan(0, 0, EFS.RC.CC.Config.Settings.AgentDialTimeOutAfterSeconds)))
			{
				// resume
				operatorDialInSession.BeginCancelDial();
			}
		}

		/// <summary>
		/// Customer service office conference terminated
		/// </summary>
		/// <param name="operatorDialInSession"></param>
		private void OnOperatorDialInSessionTerminated(EFS.RC.CC.Sessions.OfficeService.IParticipant operatorDialInSession)
		{
			// check
			EFS.Common.Verify.Reference(operatorDialInSession, "operatorDialInSession");

			// check mine
			EFS.Common.Verify.Condition(this.operatorDialInSession.Equals(operatorDialInSession), "Terminated hunter is different");

			// set
			resumeOperatorDialInSessionEvent.Set();

			// close
			BeginAsyncProcess2(CloseAgentDialTimeOutEvent);
		}

		/// <summary>
		/// Close event
		/// </summary>
		private void CloseAgentDialTimeOutEvent()
		{
			// set event
			resumeOperatorDialInSessionEvent.Close();
		}

		/// <summary>
		/// ExecuteAgentDialTimeOut complete
		/// </summary>
		/// <param name="ar"></param>
		private void OnExecuteAgentDialTimeOutComplete(EFS.Common.Async.AsyncProcess ap)
		{
			// log
			EFS.EventLog.Log.LogInfo("OnExecuteAgentDialTimeOutComplete", this);

			try
			{
				// check
				ap.Throw();

				// log
				EFS.EventLog.Log.LogInfo("OnExecuteAgentDialTimeOutComplete SUCCCESS", this);
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);
			}
		}

		#endregion
	}
}
